"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : security_sm3
Case Name   : 加密方式sm3，创建用户后修改认证方式为非sm3，可以连接数据库
Create At   : 2021/6/10
Owner       : opentestcase003
Description :
    1.修改password_encryption_type=3
    2.创建用户user001
    3.pg_hba.conf文件中增加认证方式为sm3
    4.使用user001登录数据库
    5.将步骤中的认证方式修改为sha256，再次用user001连接数据库
Expect      :
    1.参数设置成功
    2-3.认证方式添加后用户创建成功
    4.数据库连接成功
    5.数据库连接失败，报错：
History     :
           modified by opentestcase003 2021/06/21调整清理pg_hba.conf文件的步骤至第一步
           modified by opentestcase003 2021/06/29规避加密方式不为3时白名单文件被修改
           modified by opentestcase003 2021/07/01恢复默认参数步骤提到清理用户步骤之前
           modified by opentestcase003 2021/07/21备份白名单文件的操作放置在setUp\
           modified by opentestcase003 2021/10/12适配2.1.0版本
"""
import os
import unittest
from yat.test import Node
from yat.test import macro
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Logger import Logger


class Security(unittest.TestCase):
    def setUp(self):
        self.logger = Logger()
        self.logger.info('--Opengauss_Function_Security_sm3_Case0001 start--')
        self.userNode = Node('PrimaryDbUser')
        self.DB_ENV_PATH = macro.DB_ENV_PATH
        self.DB_INSTANCE_PATH = macro.DB_INSTANCE_PATH
        self.sh_primy = CommonSH('PrimaryDbUser')
        self.common = Common()
        self.user = 'u_security_sm3_0001'
        self.config = os.path.join(self.DB_INSTANCE_PATH, 'pg_hba.conf')
        self.confignew = os.path.join(self.DB_INSTANCE_PATH, 'pg_hba_bak.conf')
        self.default_msg_list = ''
        self.logger.info('--------检查参数默认值---------')
        check_default = 'show password_encryption_type;'
        default_msg = self.sh_primy.execut_db_sql(check_default)
        self.logger.info(default_msg)
        self.default_msg_list = default_msg.splitlines()[2].strip()
        self.logger.info(self.default_msg_list)
        self.logger.info('--------备份白名单文件---------')
        cp_cmd = f"cp {self.config} {self.confignew}"
        self.userNode.sh(cp_cmd).result()
    
    def test_encrypted(self):
        text = '---step1:修改password_encryption_type=3;expect:成功---'
        self.logger.info(text)
        exe_cmd1 = f'source {self.DB_ENV_PATH};' \
            f'gs_guc reload -D {self.DB_INSTANCE_PATH} -c ' \
            '"password_encryption_type=3"'
        msg1 = self.userNode.sh(exe_cmd1).result()
        self.logger.info(msg1)
        check_cmd = 'show password_encryption_type;'
        check_msg = self.sh_primy.execut_db_sql(check_cmd)
        self.logger.info(check_msg)
        self.common.equal_sql_mdg(check_msg, 'password_encryption_type', '3',
                                  '(1 row)', flag='1')
        text = '---step2:创建用户1；expect:成功---'
        self.logger.info(text)
        sql_cmd2 = f'create user {self.user} with password \'' \
            f'{macro.COMMON_PASSWD}\';'
        msg2 = self.sh_primy.execut_db_sql(sql_cmd2)
        self.logger.info(msg2)
        self.assertIn('CREATE ROLE', msg2, '执行失败:' + text)
        text = '---step3:pg_hba.conf文件中增加认证方式为sm3；expect:成功---'
        self.logger.info(text)
        guc_cmd = f'source {macro.DB_ENV_PATH};' \
            f'gs_guc reload -D {macro.DB_INSTANCE_PATH} -h ' \
            f'"local all all sm3"'
        guc_msg = self.userNode.sh(guc_cmd).result()
        self.logger.info(guc_msg)
        text = '---step4:使用用户1登录数据库；expect:成功---'
        self.logger.info(text)
        exe_cmd3 = f'source {self.DB_ENV_PATH};' \
            f'gsql -d {self.userNode.db_name} -p ' \
            f'{self.userNode.db_port} -U {self.user} -W \'' \
            f'{macro.COMMON_PASSWD}\' -c "\\q"'
        self.logger.info(exe_cmd3)
        msg3 = self.userNode.sh(exe_cmd3).result()
        self.logger.info(msg3)
        self.assertEqual('', msg3, '执行失败:' + text)
        text = '--step5:将认证方式修改为sha256，再次用用户1连接数据库；expect:失败--'
        self.logger.info(text)
        guc_cmd4 = f'source {macro.DB_ENV_PATH};' \
            f'gs_guc reload -D {macro.DB_INSTANCE_PATH} -h ' \
            f'"local all all sha256"'
        guc_msg4 = self.userNode.sh(guc_cmd4).result()
        self.logger.info(guc_msg4)
        exe_cmd5 = f'source {self.DB_ENV_PATH};' \
            f'gsql -d {self.userNode.db_name} -p ' \
            f'{self.userNode.db_port} -U {self.user} -W \'' \
            f'{macro.COMMON_PASSWD}\' -c "\\q"'
        self.logger.info(exe_cmd5)
        msg5 = self.userNode.sh(exe_cmd5).result()
        self.logger.info(msg5)
        self.assertIn("Invalid username/password,login denied", msg5,
                      '执行失败:' + text)
    
    def tearDown(self):
        self.logger.info('-------1.恢复配置文件中的信息------')
        check_cmd = f'if [ -f {self.config} ];then mv {self.confignew} ' \
            f'{self.config};fi'
        self.logger.info(check_cmd)
        self.userNode.sh(check_cmd).result()
        restart_cmd = f'source {macro.DB_ENV_PATH};' \
            f'gs_ctl restart -D {macro.DB_INSTANCE_PATH} -M primary'
        restart_msg = self.userNode.sh(restart_cmd).result()
        self.logger.info(restart_msg)
        self.logger.info('-------2.恢复加密方式配置------')
        exe_cmd1 = f'source {self.DB_ENV_PATH};' \
            f'gs_guc reload -D {self.DB_INSTANCE_PATH} -c ' \
            f'"password_encryption_type={self.default_msg_list}"'
        msg1 = self.userNode.sh(exe_cmd1).result()
        self.logger.info(msg1)
        sql_cmd2 = 'show password_encryption_type;'
        msg2 = self.sh_primy.execut_db_sql(sql_cmd2)
        self.logger.info(msg2)
        self.logger.info('-------3.删除用户------')
        sql_cmd3 = f'drop user {self.user}'
        msg3 = self.sh_primy.execut_db_sql(sql_cmd3)
        self.logger.info(msg3)
        self.logger.info(
            '----Opengauss_Function_Security_sm3_Case0001 finish----')
